﻿using System.Security.Cryptography;
using System.Text;

namespace Mafool.Core;

public static class Security
{
    // 参数模型：CRC-16/AUG-CCITT
    public static byte[] CRC16(byte[] p, int datalen)
    {
        byte CRC16Lo, CRC16Hi, CL, CH, SaveHi, SaveLo;
        int i, Flag;
        CRC16Lo = 0xFF;
        CRC16Hi = 0xFF;
        CL = 0x01;
        CH = 0xA0;
        for (i = 0; i < datalen; i++)
        {
            CRC16Lo ^= p[i]; //每一个数据与 CRC 寄存器进行异或
            for (Flag = 0; Flag < 8; Flag++)
            {
                SaveHi = CRC16Hi;
                SaveLo = CRC16Lo;
                CRC16Hi >>= 1;
                CRC16Lo >>= 1; //高位右移一位，低位右移一位
                if ((SaveHi & 0x01) == 0x01) //如果高位字节最后一位为 1
                    CRC16Lo |= 0x80; //则低位字节右移后前面补 1 否则自动补 0
                if ((SaveLo & 0x01) == 0x01) //如果 LSB 为 1，则与多项式码进行异或
                {
                    CRC16Hi ^= CH;
                    CRC16Lo ^= CL;
                }
            }
        }

        byte[] crc = { CRC16Lo, CRC16Hi };
        return crc;
    }


    /// <summary>
    /// 32位MD5加密
    /// </summary>
    public static string Md5(this string s)
    {
        using MD5 md5 = MD5.Create();
        byte[] hashBytes = md5.ComputeHash(Encoding.UTF8.GetBytes(s));

        StringBuilder sb = new();
        foreach (var t in hashBytes)
        {
            sb.Append(t.ToString("x2"));
        }

        return sb.ToString();
    }


    /// <summary>
    /// Sha256加密
    /// "x2"：将每个字节转换为两位的小写十六进制字符串（例如，a-f中的字符）。
    /// "X2"：将每个字节转换为两位的大写十六进制字符串（例如，A-F中的字符）。
    /// "d"：将哈希值视为有符号十进制整数进行显示。
    /// "D"：将哈希值视为无符号十进制整数进行显示。
    /// "N"：将哈希值视为纯数字（无分隔符）进行显示。
    /// </summary>
    public static string Sha256(this string s, string format = "x2")
    {
        using SHA256 sha256 = SHA256.Create();
        byte[] inputBytes = Encoding.UTF8.GetBytes(s);
        byte[] hashBytes = sha256.ComputeHash(inputBytes);

        StringBuilder sb = new();
        foreach (var t in hashBytes)
        {
            sb.Append(t.ToString(format));
        }
        return sb.ToString();
    }

    /// <summary>
    /// Base64编码
    /// </summary>
    public static string Base64Encode(this string s)
    {
        return Convert.ToBase64String(Encoding.UTF8.GetBytes(s));
    }

    /// <summary>
    /// Base64解码
    /// </summary>
    public static string Base64Decode(this string s)
    {
        return Encoding.UTF8.GetString(Convert.FromBase64String(s));
    }
}